# -*- coding: utf-8 -*-
#! /usr/bin/python
#######################################################################################
#                                                                                     #
#    File: main.py                                                                    #
#    Part of 21th-cheater                                                             #
#    Home: http://21th-cheater.googlecode.com                                         #
#                                                                                     #
#    The MIT License                                                                  #
#                                                                                     #
#    Copyright (c) 2010-2011 <elsesky@gmail.com>                                      #
#                                                                                     #
#    Permission is hereby granted, free of charge, to any person obtaining a copy     #
#    of this software and associated documentation files (the "Software"), to deal    #
#    in the Software without restriction, including without limitation the rights     #
#    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell        #
#    copies of the Software, and to permit persons to whom the Software is            #
#    furnished to do so, subject to the following conditions:                         #
#                                                                                     #
#    The above copyright notice and this permission notice shall be included in       #
#    all copies or substantial portions of the Software.                              #
#                                                                                     #
#    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR       #
#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,         #
#    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE      #
#    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER           #
#    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,    #
#    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN        #
#    THE SOFTWARE.                                                                    #
#                                                                                     #
#######################################################################################
'''
Created on May 9, 2013

@author: elsesky
@modified by: elsesky
'''
import time, datetime, sys
import random
import sqlite3
import browser_bogus
import online_keeper
import urllib2

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from ui.Core import *
from user_agent_lib import get_random_user_agent
from ntpsocket import get_ntp_time
from com_lib import *

VERSION = "1.5.5"

online_keeper_threads = []
lession_selector_threads = []
lession_selector_by_credit_threads = []

online_keeper_accounts = []

app = QApplication(sys.argv)
window = MainWindow()
online_keeper_update_timer = QTimer()
lession_selector_update_timer = QTimer()
lession_selector_credit_update_timer = QTimer()


try:
    _fromUtf8 = QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s
    

class OnlineKeeperWorker(QThread):
    learnedtime = 120
    refreshtime = 60
    relogintime = 3600
    relogintime_indicator = 3600
    #设定重选课间隔60*60*24/10/2
    refreshtime_lession_selector = 3600
    relogintime_lession_selector = 3600
    
#     relogintime_lession_selector = 10
    lessionnum = 2
    creditnum = 2
    totaldone = 0
    
    def __init__(self, username, passwd, itemdata, parent=None):
        super(OnlineKeeperWorker, self).__init__(parent)
        self.browser = browser_bogus.Browser(username, passwd, get_random_user_agent())
#        self.setDaemon(True)
#        self.stopevent = threading.Event()
        self.itemdata = itemdata
      
    def set_learnedtime(self,learnedtime):
        self.learnedtime = learnedtime
    
    def set_refreshtime(self,refreshtime):
        self.refreshtime = refreshtime
        
    def set_lessionnum(self,lessionnum):
        self.lessionnum = lessionnum
        
    def set_creditnum(self,creditnum):
        self.creditnum = creditnum
        
    def set_relogintime(self,relogintime):
        self.relogintime_indicator = relogintime
        self.relogintime = relogintime
        
    def set_refreshtime_lession_selector(self,refreshtime_lession_selector):
        #传进来的是小时数，转换为秒
#         self.refreshtime_lession_selector = refreshtime_lession_selector * 10
#         self.relogintime_lession_selector = refreshtime_lession_selector * 10
        self.refreshtime_lession_selector = refreshtime_lession_selector * 3600
        self.relogintime_lession_selector = refreshtime_lession_selector * 3600
#         self.refreshtime_lession_selector = refreshtime_lession_selector
#         self.relogintime_lession_selector = refreshtime_lession_selector
    
    def login(self):
#        print "UA: ", self.browser.user_agent
        try:
            self.itemdata[2] = _fromUtf8("正在登录")
            self.sleep(1)
            online_keeper.do_login(self.browser)
            self.itemdata[2] = _fromUtf8("已登录")
            self.sleep(1)
        except online_keeper.LoginFailed:
            self.itemdata[2] = _fromUtf8("登录失败")
        except urllib2.URLError:
            self.itemdata[2] = _fromUtf8("网络连接不正常")
        except urllib2.HTTPError, err:
            self.itemdata[2] = _fromUtf8("请求被拒绝 %d" % err.code)
        except:
            self.itemdata[2] = _fromUtf8("未知异常")
            
    def refresh(self,learnedtime="120",refreshtime=60):
        fname = "sysrun.log"
        while True:
            #获取开始时间戳
            stime = int(time.time())
            try:
                self.itemdata[2] = _fromUtf8("刷新课程中")
                self.sleep(1)
                online_keeper.update_lt(self.browser,learnedtime)
                self.itemdata[2] = _fromUtf8("刷新完毕")
                self.sleep(1)
            except urllib2.URLError:
                self.itemdata[2] = _fromUtf8("网络连接不正常")
            except urllib2.HTTPError, err:
                self.itemdata[2] = _fromUtf8("请求被拒绝 %d" % err.code)
            except:
                self.itemdata[2] = _fromUtf8("未知异常")

            print "执行完毕".decode("utf-8").encode("gbk")
            logd(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))+ "===========" + "执行完毕".decode("utf-8").encode("gbk") + "\r\n")
            i = refreshtime
            self.totaldone += 1
            #同时计算超时设置
            while True:
                self.itemdata[2] = _fromUtf8("完毕.将在" + str(i-1) +"秒后刷新，共执行" + str(self.totaldone) + "次") 
                i -= 1
                #重新选课的倒计时(整合进时间戳里面计算)
#                 self.refreshtime_lession_selector -= 1
                if i < 1:
                    break
                self.sleep(1)
            #计时重登陆，避免SESSION超期
#             self.relogintime -= refreshtime
            #修改为取实际执行耗时
            retime = int(time.time())
            totalrtime = retime - stime
            self.relogintime -= totalrtime
            print "剩余重登录时间为:".decode("utf-8").encode("gbk") + str(self.relogintime)
            logd(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))+ "===========" + "剩余重登录时间为:".decode("utf-8").encode("gbk") + str(self.relogintime) + "\r\n")
            if self.relogintime <= 0:
                print "relogin"
                logd(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))+ "===========" + "relogin" + "\r\n")
#                 try:
#                     fp = open(fname, "a")
#                     fp.write(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))+ "===========" + str("do relogin\r\n"))
#                 except IOError:
#                     print "log err"
                
                self.relogintime = self.relogintime_indicator
                self.logout()
                self.login()
#                 fp.write(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))+ "===========" + str("relogin done\r\n"))
                logd(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))+ "===========" + "relogin done" + "\r\n")
                
            
            etime = int(time.time())
            totalctime = etime - stime
            #减去花掉的时间
            self.refreshtime_lession_selector -= totalctime
            print "刷课花费时间:".decode("utf-8").encode("gbk") + str(totalctime)
            logd(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))+ "===========" + "刷课花费时间:".decode("utf-8").encode("gbk") + str(totalctime) + "\r\n")
            #计时选课
            print "剩余选课时间为:".decode("utf-8").encode("gbk") + str(self.refreshtime_lession_selector)
            logd(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))+ "===========" + "剩余选课时间为:".decode("utf-8").encode("gbk") + str(self.refreshtime_lession_selector) + "\r\n")
            if self.refreshtime_lession_selector <= 0:
                 #当同时启用选课设置时，进入选课设置
                if window.get_checkbox_lession_select_in_refresh_state():
                    #判断按照何种方式选课(学分或课程数)
                    if window.get_radioButton_lession_select_in_refresh_by_credit_state():
                        print "开始按学分设置选课".decode("utf-8").encode("gbk")
                        logd(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))+ "===========" + "开始按学分设置选课".decode("utf-8").encode("gbk") + "\r\n")
                        #重置选课倒计时
                        self.refreshtime_lession_selector = self.relogintime_lession_selector
                        self.itemdata[2] = _fromUtf8("选课中")
                        self.sleep(1)
                        online_keeper.select_lession_by_credit(self.browser,self.creditnum)
                        self.itemdata[2] = _fromUtf8("选课完成")
                        self.sleep(1)
                    else:
                        print "开始按课程数设置选课".decode("utf-8").encode("gbk")
                        logd(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))+ "===========" + "开始按课程数设置选课".decode("utf-8").encode("gbk") + "\r\n")
                        #重置选课倒计时
                        self.refreshtime_lession_selector = self.relogintime_lession_selector
                        self.itemdata[2] = _fromUtf8("选课中")
                        self.sleep(1)
                        online_keeper.select_lession(self.browser,self.lessionnum)
                        self.itemdata[2] = _fromUtf8("选课完成")
                        self.sleep(1)
                    logd(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))+ "===========" + "选课完成".decode("utf-8").encode("gbk") + "\r\n")
                    
#         fp.close()
           
    def logout(self):
        self.itemdata[2] = _fromUtf8("正在注销")
        online_keeper.logout(self.browser)
        self.itemdata[2] = _fromUtf8("已注销")
        
    def run(self):
        while True:
            self.login()
            self.refresh(self.learnedtime,self.refreshtime)
            self.logout()
        
        self.login()
        self.exec_()
    
    def quit(self):
        self.logout()
        self.itemdata[2] = _fromUtf8("已停止")
        super(OnlineKeeperWorker, self).quit()
                       
class LessionSelectorWorker(QThread):
    learnedtime = "80"
    refreshtime = 10
    relogintime = 3600
    lessionnum = 2
    
    totaldone = 0
    def __init__(self, username, passwd, itemdata, parent=None):
        super(LessionSelectorWorker, self).__init__(parent)
        self.browser = browser_bogus.Browser(username, passwd, get_random_user_agent())
        self.itemdata = itemdata
        
    def login(self):
#        print "UA: ", self.browser.user_agent
        try:
            self.itemdata[2] = _fromUtf8("正在登录")
            self.sleep(1)
            online_keeper.do_login(self.browser)
            self.itemdata[2] = _fromUtf8("已登录")
            self.sleep(1)
        except online_keeper.LoginFailed:
            self.itemdata[2] = _fromUtf8("登录失败")
        except urllib2.URLError:
            self.itemdata[2] = _fromUtf8("网络连接不正常")
        except urllib2.HTTPError, err:
            self.itemdata[2] = _fromUtf8("请求被拒绝 %d" % err.code)
        except:
            self.itemdata[2] = _fromUtf8("未知异常")
    
    def logout(self):
        online_keeper.logout(self.browser)
        
    def refresh(self,learnedtime="120",refreshtime=60,lessionnum=2):
        self.itemdata[2] = _fromUtf8("选课中")
        self.sleep(1)
        online_keeper.select_lession(self.browser,lessionnum)
        self.itemdata[2] = _fromUtf8("选课完成")
        self.sleep(1)
        
#         
#         while True:
#             try:
#                 self.itemdata[2] = _fromUtf8("刷新课程中")
#                 self.sleep(1)
#                 online_keeper.update_lt(self.browser,learnedtime)
#                 self.itemdata[2] = _fromUtf8("刷新完毕")
#                 self.sleep(1)
#             except:
#                 self.itemdata[2] = _fromUtf8("未知异常")
#             print "执行完毕".decode("utf-8").encode("gbk")
#             i = refreshtime
#             #计时重登陆，避免SESSION超期
#             self.relogintime -= refreshtime
#             if self.relogintime <= 0:
#                 print "relogin"
#                 self.relogintime = 3600
#                 self.logout()
#                 self.login()
    def run(self):
        self.login()
        self.refresh(self.learnedtime,self.refreshtime,self.lessionnum)
        self.logout()
        
        #set button status to enable
        window.lession_selector_start()
        super(LessionSelectorWorker, self).quit()
    def set_learnedtime(self,learnedtime):
        self.learnedtime = learnedtime
    
    def set_refreshtime(self,refreshtime):
        self.refreshtime = refreshtime
        
    def set_lessionnum(self,lessionnum):
        self.lessionnum = lessionnum
        
    def quit(self):
        self.logout()
        super(LessionSelectorWorker, self).quit()

class LessionSelectorByCreditWorker(QThread):
    learnedtime = "80"
    refreshtime = 10
    relogintime = 3600
    lessionnum = 2
    creditnum = 2
    
    totaldone = 0
    def __init__(self, username, passwd, itemdata, parent=None):
        super(LessionSelectorByCreditWorker, self).__init__(parent)
        self.browser = browser_bogus.Browser(username, passwd, get_random_user_agent())
        self.itemdata = itemdata
        
    def login(self):
#        print "UA: ", self.browser.user_agent
        try:
            self.itemdata[2] = _fromUtf8("正在登录")
            self.sleep(1)
            online_keeper.do_login(self.browser)
            self.itemdata[2] = _fromUtf8("已登录")
            self.sleep(1)
        except online_keeper.LoginFailed:
            self.itemdata[2] = _fromUtf8("登录失败")
        except urllib2.URLError:
            self.itemdata[2] = _fromUtf8("网络连接不正常")
        except urllib2.HTTPError, err:
            self.itemdata[2] = _fromUtf8("请求被拒绝 %d" % err.code)
        except:
            self.itemdata[2] = _fromUtf8("未知异常")
    
    def logout(self):
        online_keeper.logout(self.browser)
        
    def refresh(self,learnedtime="120",refreshtime=60,creditnum=2):
        self.itemdata[2] = _fromUtf8("选课中")
        self.sleep(1)
        online_keeper.select_lession_by_credit(self.browser,creditnum)
        self.itemdata[2] = _fromUtf8("选课完成")
        self.sleep(1)
        
    def run(self):
        self.login()
        self.refresh(self.learnedtime,self.refreshtime,self.creditnum)
        self.logout()
        
        #set button status to enable
        window.lession_selector_start()
        super(LessionSelectorByCreditWorker, self).quit()
    def set_learnedtime(self,learnedtime):
        self.learnedtime = learnedtime
    
    def set_refreshtime(self,refreshtime):
        self.refreshtime = refreshtime
        
    def set_lessionnum(self,lessionnum):
        self.lessionnum = lessionnum
    
    def set_creditnum(self,creditnum):
        self.creditnum = creditnum    
        
    def quit(self):
        self.logout()
        super(LessionSelectorWorker, self).quit()
    
def read_account(filename="accounts.db"):
#    file = open(filename, "r")
#    lines = file.readlines()
#    file.close()
#    
#    for line in lines:
#        if line[0] == "#":
#            continue
#        if line[0] == "o":
#            account_data = line.strip().split(",")[1:]
#            online_keeper_accounts.append([QString.fromUtf8(account_data[0]),
#                                           QString.fromUtf8(account_data[1]),
#                                           QString.fromUtf8('##')])
#        if line[0] == "d":
#            account_data = line.strip().split(",")[1:]
#            daily_job_accounts.append([QString.fromUtf8(account_data[0]),
#                                       QString.fromUtf8(account_data[1]),
#                                       QString.fromUtf8('##'),
#                                       QString.fromUtf8('##')])
            
    conn = sqlite3.connect(filename)
    c = conn.cursor()
    
    c.execute("""SELECT * FROM online_keeper_accounts""")
    items = c.fetchall()
    for item in items:
        online_keeper_accounts.append([QString(item[0]),
                                       QString(item[1]),
                                       QString.fromUtf8('##')])
        

        
    conn.close()
        
def write_account(filename="accounts.db"):
    conn = sqlite3.connect(filename)
    c = conn.cursor()
    c.execute("DROP TABLE online_keeper_accounts")
    c.execute("""CREATE TABLE online_keeper_accounts 
                 (username TEXT PRIMARY KEY, passwd TEXT)""")
    for item in online_keeper_accounts:
        c.execute("INSERT INTO online_keeper_accounts VALUES (?,?)",
                  (item[0].__str__(), item[1].__str__()))

    conn.commit()
    conn.close()
#    file = open(filename, "w")
#    for item in online_keeper_accounts:
#        if QString.toUtf8(item[0]) == "##":
#                continue
#        file.write("o," + QString.toUtf8(item[0]) + "," + QString.toUtf8(item[1]) + "\n")
#    for item in daily_job_accounts:
#        if QString.toUtf8(item[0]) == "##":
#                continue
#        file.write("d," + QString.toUtf8(item[0]) + "," + QString.toUtf8(item[1]) + "\n")
#        
#    file.close()
        
        
#    print daily_job_threads
#    print online_keeper_threads
            
def start_online_keeper():
    learnedtime = _fromUtf8(window.get_learnedtime())
    refreshtime = int(_fromUtf8(window.get_refreshtime()))
    lessionnum = int(_fromUtf8(window.get_lession_num()))
    creditnum =  int(_fromUtf8(window.get_credit_num()))
    refreshtime_lession_selector = int(_fromUtf8(window.get_refreshtime_lession_selector()))
    relogintime = int(_fromUtf8(window.get_relogin_time()))
    
    window.online_keeper_start()
#     print window.pushButton_online_keeper_start.state
    if window.pushButton_online_keeper_start.state:
        for item in online_keeper_accounts:
            worker = OnlineKeeperWorker(QString.toUtf8(item[0]), 
                                        QString.toUtf8(item[1]), item) 
            worker.set_learnedtime(learnedtime)
            worker.set_refreshtime(refreshtime)
            worker.set_lessionnum(lessionnum)
            worker.set_creditnum(creditnum)
            worker.set_relogintime(relogintime)
            worker.set_refreshtime_lession_selector(refreshtime_lession_selector)
            online_keeper_threads.append(worker)
        for worker in online_keeper_threads:
            worker.start()
        print online_keeper_threads
        online_keeper_update_timer.start(1000)
    else:
        print "stop workers"
        for worker in online_keeper_threads:
            worker.quit()
        online_keeper_update_timer.stop()
        while len(online_keeper_threads) > 0:
            online_keeper_threads.pop()
        print online_keeper_threads
 
def start_select_lesson():
    learnedtime = _fromUtf8(window.get_learnedtime())
    refreshtime = int(_fromUtf8(window.get_refreshtime()))
    lessionnum = int(_fromUtf8(window.get_lession_num()))
    window.lession_selector_start()
    if window.pushButton_online_keeper_start.state:
        for item in online_keeper_accounts:
            worker = LessionSelectorWorker(QString.toUtf8(item[0]), 
                                        QString.toUtf8(item[1]), item) 
            worker.set_learnedtime(learnedtime)
            worker.set_refreshtime(refreshtime)
            worker.set_lessionnum(lessionnum)
            lession_selector_threads.append(worker)
        for worker in lession_selector_threads:
            worker.start()
        print lession_selector_threads
        lession_selector_update_timer.start(1000)
    else:
        print "stop workers"
        for worker in lession_selector_threads:
            worker.quit()
        lession_selector_update_timer.stop()
        while len(lession_selector_threads) > 0:
            lession_selector_threads.pop()
        print lession_selector_threads

def start_select_by_credit():
    learnedtime = _fromUtf8(window.get_learnedtime())
    refreshtime = int(_fromUtf8(window.get_refreshtime()))
    lessionnum = int(_fromUtf8(window.get_lession_num()))
    creditnum =  int(_fromUtf8(window.get_credit_num()))
    
    window.lession_selector_by_credit_start()
    if window.pushButton_online_keeper_start.state:
        for item in online_keeper_accounts:
            worker = LessionSelectorByCreditWorker(QString.toUtf8(item[0]), 
                                        QString.toUtf8(item[1]), item) 
            worker.set_learnedtime(learnedtime)
            worker.set_refreshtime(refreshtime)
            worker.set_lessionnum(lessionnum)
            worker.set_creditnum(creditnum)
            lession_selector_by_credit_threads.append(worker)
        for worker in lession_selector_by_credit_threads:
            worker.start()
        print lession_selector_by_credit_threads
        lession_selector_credit_update_timer.start(1000)
    else:
        print "stop workers"
        for worker in lession_selector_by_credit_threads:
            worker.quit()
        lession_selector_credit_update_timer.stop()
        while len(lession_selector_by_credit_threads) > 0:
            lession_selector_by_credit_threads.pop()
        print lession_selector_by_credit_threads
    return
   


#定义单选框的信号处理
def checkbox_lession_select_in_refresh_onclick():
    #如果是已经勾上的状态则禁止掉其它两个
    window.checkbox_lession_select_in_refresh_onclick()
    
#     print window.get_checkbox_lession_select_in_refresh_state()
#     print window.get_radioButton_lession_select_in_refresh_by_lessionnum_state()
#     print window.get_radioButton_lession_select_in_refresh_by_credit_state()
    return



if __name__ == "__main__":
    random.seed()
    try:
        read_account()
    except:
        QMessageBox.information(window, _fromUtf8("错误"),
                    _fromUtf8("无法打开账户文件accounts.db"))
    
    window.update_online_keeper_account_list(online_keeper_accounts)
    window.init_display_properties()
    window.init_signals()
    QObject.connect(online_keeper_update_timer,
                    SIGNAL(_fromUtf8("timeout()")),
                    window.online_keeper_account_list.reset)
    QObject.connect(window.pushButton_online_keeper_start,
                    SIGNAL(QString.fromUtf8("clicked()")),
                    start_online_keeper)
    QObject.connect(window.online_keeper_dataModel,
                    SIGNAL(QString.fromUtf8("dataChanged()")),
                    write_account)
    QObject.connect(window.pushButton,
                    SIGNAL(QString.fromUtf8("clicked()")),
                    start_select_lesson)
    QObject.connect(window.pushButton_lession_selector_by_credit,
                    SIGNAL(QString.fromUtf8("clicked()")),
                    start_select_by_credit)
    #关联单选框信号
    QObject.connect(window.checkbox_lession_select_in_refresh,
                    SIGNAL(QString.fromUtf8("clicked()")),
                    checkbox_lession_select_in_refresh_onclick)
    
    window.write_account_signal.connect(write_account)
    
    QApplication.setQuitOnLastWindowClosed(False)
    window.show()
    
    sys.exit(app.exec_())